const { execSync } = require("child_process");
const path = require("path");

function ensureDependencies() {
    const dependencies = ["ws", "protobufjs"];
    dependencies.forEach((dep) => {
        try {
            // 检查依赖是否已安装
            require.resolve(dep);
            console.log(`Dependency '${dep}' is already installed.`);
        } catch (e) {
            console.log(`Dependency '${dep}' is missing. Installing...`);
            try {
                // 安装缺失的依赖
                execSync(`npm install ${dep}`, { stdio: "inherit" });
                console.log(`Dependency '${dep}' has been successfully installed.`);
            } catch (installError) {
                console.error(`Failed to install '${dep}':`, installError.message);
                process.exit(1); // 如果安装失败，则退出程序
            }
        }
    });
}

// 在启动服务器前确保所有依赖已安装
ensureDependencies();

// 引入依赖
const WebSocket = require("ws");
const net = require("net");
const protobuf = require("protobufjs");

// 定义 .proto 文件路径
const PROTO_HEADER_PATH = path.resolve(__dirname, "./PackHeader.proto");
const PROTO_BODY_PATH = path.resolve(__dirname, "./PackData.proto");

let Header, Body;

// 加载 PackHeader.proto 文件
protobuf.load(PROTO_HEADER_PATH, (err, root) => {
    if (err) {
        console.error("Failed to load PackHeader.proto:", err);
        process.exit(1); // 退出程序
    }
    Header = root.lookupType("PackHeader.Header");
    console.log("Header type loaded successfully");
});

// 加载 PackData.proto 文件
protobuf.load(PROTO_BODY_PATH, (err, root) => {
    if (err) {
        console.error("Failed to load PackData.proto:", err);
        process.exit(1); // 退出程序
    }
    Body = root.lookupType("PackData.Body");
    console.log("Body type loaded successfully");
});

// TCP 服务器信息
const TCP_SERVER_HOST = "127.0.0.1";
const TCP_SERVER_PORT = 7894;

// WebSocket 代理服务器端口
const WS_PORT = 8080;

// 启动 WebSocket 服务器
const wss = new WebSocket.Server({ port: WS_PORT });
console.log(`WebSocket-TCP proxy listening on ws://127.0.0.1:${WS_PORT}`);

wss.on("connection", (ws) => {
    console.log("New WebSocket connection");

    // 创建 TCP 客户端连接到 TCP 服务器
    const tcpClient = new net.Socket();
    tcpClient.connect(TCP_SERVER_PORT, TCP_SERVER_HOST, () => {
        console.log("Connected to TCP server");
    });

    // WebSocket -> TCP 转发
    ws.on("message", (message) => {
        try {
            console.log("WebSocket message received:", message);

            // 解析 WebSocket 消息
            const parsedMessage = JSON.parse(message);
            // 构造 Header 和 Body 的 Protobuf 数据
            const header = Header.create({
                appId: parsedMessage.appId || 1,
                uid: parsedMessage.sender_id,
                token: "valid-token",
                bizId: parsedMessage.biz_id,//业务 ID 如果登录是1 然后切换上行消息是3
                messageType: parsedMessage.message_type,
                compression: 0,
                encryption: 0,
            });

            const body = Body.create({
                data: JSON.stringify({
                    sender_id: parsedMessage.sender_id,
                    receiver_id: parsedMessage.receiver_id,
                    context: parsedMessage.context,
                    timestamp: Date.now(),  // 添加时间戳
                    message_id: 12345678,  // 生成消息ID
                    message_type: 1,  // 假设1是文本消息
                    session_id: parsedMessage.session_id
                }),
            });


            const headerBytes = Header.encode(header).finish();
            const bodyBytes = Body.encode(body).finish();

            // 构造完整的二进制数据包
            const packetBoundary = 0xABCD;
            const version = 1;
            const packetHeaderLength = headerBytes.length;
            const packetBodyLength = bodyBytes.length;

            const binaryMessage = Buffer.alloc(16 + headerBytes.length + bodyBytes.length);
            binaryMessage.writeUInt32BE(packetBoundary, 0);
            binaryMessage.writeUInt32BE(version, 4);
            binaryMessage.writeUInt32BE(packetHeaderLength, 8);
            binaryMessage.writeUInt32BE(packetBodyLength, 12);
            headerBytes.copy(binaryMessage, 16);
            bodyBytes.copy(binaryMessage, 16 + headerBytes.length);

            // 转发给 TCP 服务器
            tcpClient.write(binaryMessage);
        } catch (error) {
            console.error("Error processing WebSocket message:", error);
        }
    });

    // TCP -> WebSocket 转发
    tcpClient.on("data", (data) => {
        try {
            console.log("TCP server response received, length:", data.length);

            // 解码 TCP 响应
            if (data.length < 16) {
                console.error("Invalid response format: insufficient length");
                return;
            }

            // 提取包头信息
            const packetBoundary = data.readUInt32BE(0);
            const version = data.readUInt32BE(4);
            const headerLength = data.readUInt32BE(8);
            const bodyLength = data.readUInt32BE(12);

            if (packetBoundary !== 0xABCD) {
                console.error("Invalid packet boundary in response");
                return;
            }

            // 提取 Header 和 Body 数据
            const headerBytes = data.slice(16, 16 + headerLength);
            const bodyBytes = data.slice(16 + headerLength, 16 + headerLength + bodyLength);

            // 反序列化 Protobuf 数据
            const header = Header.decode(headerBytes);
            const body = Body.decode(bodyBytes);

            // 转发给 WebSocket 客户端
            ws.send(JSON.stringify({ header, body }));
        } catch (error) {
            console.error("Error decoding TCP response:", error);
        }
    });

    // WebSocket 关闭时，关闭 TCP 连接
    ws.on("close", () => {
        console.log("WebSocket connection closed");
        tcpClient.end();
    });

    // TCP 关闭时，关闭 WebSocket 连接
    tcpClient.on("close", () => {
        console.log("TCP server connection closed");
        ws.close();
    });

    // 错误处理
    ws.on("error", (error) => {
        console.error("WebSocket error:", error);
        tcpClient.end();
    });

    tcpClient.on("error", (error) => {
        console.error("TCP error:", error);
        ws.close();
    });
});
